//
//  WJStatusListViewModel.swift
//  新浪微博swift
//
//  Created by WJ-Jason on 2017/5/3.
//  Copyright © 2017年 WJ-Jason. All rights reserved.
//

import Foundation
import SDWebImage

// 微博数据列表视图模型
/*
    父类的选择
 
 - 如果类需要使用‘KVC’ 或者字典转模型框架设置对象值,类就需要继承自NSObject
 - 如果类只是包装一些代码逻辑(写了一些函数),可以不用任何父类,好处:更加轻量级
 - 提示: 如果用OC写,一律都集成自NSObject 即可
 
 使命: 负责微博的数据处理
 
*/

fileprivate let maxPullipTryTimes = 3 //上拉刷新最大尝试次数

class WJStatusListViewModel {
    
    fileprivate var pullupError = 0 // 上拉刷新错误次数
    
    /// 微博视图模型数组懒加载
    lazy var statusList = [WJStatusViewModel]()
    
    func loadStatus(pullup: Bool, completion:@escaping (_ isSuccess:Bool,_ shouldRefresh:Bool)->()) -> () {
        
        // 判断是否为上拉刷新, 同时检查刷新次数
        if pullup && pullupError > maxPullipTryTimes{
            completion(true,false)
            
            return
        }
        
        
        let since_Id = pullup ? 0 : statusList.first?.status.id ?? 0
        
        let max_id = !pullup ? 0 : statusList.last?.status.id ?? 0
        
        WJNewworkManager.shared.statusList(since_id: since_Id,max_id: max_id) { (list, isSuccess) in
            // 0.判断网络请求是否成功
            if !isSuccess {
                
                // 直接回调返回
                
                completion(false, false)
                
                return
            }
            
            
            // 1.字典转模型(所有的第三方框架都支持嵌套的字典转模型！)
            // 1>定义结果可变数组
            var array = [WJStatusViewModel]()
            
            // 2>遍历服务器返回的字典数组,字典转模型
            for dict in list ?? [] {
                
                print(dict["pic_urls"] ?? "")
                // 1.创建微博模型
                guard let model = WJSatus.yy_model(with: dict) else {
                    continue
                }
                // 2.使用微博模型 创建微博视图模型
                let viewModel = WJStatusViewModel(model: model)
                
                array.append(viewModel)
            }
            
            
            print("刷新到 \(array.count) 条数据 \(array)")
            
            // FIXME: 2.拼接数据
            if pullup {
                //上拉刷新, 把数组拼接在数组的末尾
                self.statusList += array
            }
            else {
                // 下拉刷新, 应该将结果数组拼接在数组前面
                self.statusList = array + self.statusList
            }
            
            // 3.判断上拉刷新的数据量
            if pullup && array.count == 0 {
                self.pullupError += 1

                completion(isSuccess,false)
            }
            else {
                
                self.cacheSingleImage(list: array , finished: completion)

            }
        }
    }
    
    /// 缓存本次下载微博数据数组中的单张图像
    ///
    /// - 应该缓存完单张图像，并且修改过配图是的大小之后，再回调，才能够保证表格等比例显示单张图像！
    ///
    /// - parameter list: 本次下载的视图模型数组
    private func cacheSingleImage(list: [WJStatusViewModel] , finished:@escaping (_ isSuccess:Bool,_ shouldRefresh:Bool)->()) {
        
        // 调度组********监听一组任务的完成*********
        let group = DispatchGroup()
        
        // 记录数据长度
        var length = 0
        
        // 遍历数组 查找微博中有单张图片的 进行缓存
        // option + cmd + 左, 折叠代码
        
        for vm in list {
            
            // 1> ******判断图像的数量 continue等于1就往下走 不等于1就不走下面继续遍历循环******
            if vm.picURLs?.count != 1 {
                continue //继续循环 不往下走
            }
            // 2> 代码执行到此, 数组中有且仅有一张图片
            guard let pic = vm.picURLs?[0].thumbnail_pic,
                  let url = URL(string: pic)
            else {
                continue
            }
            
            // 3> 下载图像
            // 1) downloadImage 是 SDWebImage 的核心方法
            // 2) 图像下载完成之后，会自动保存在沙盒中，文件路径是 URL 的 md5
            // 3) 如果沙盒中已经存在缓存的图像，后续使用 SD 通过 URL 加载图像，都会加载本地沙盒地图像
            // 4) 不会发起网路请求，同时，回调方法，同样会调用！
            // 5) 方法还是同样的方法，调用还是同样的调用，不过内部不会再次发起网路请求！
            // *** 注意点：如果要缓存的图像累计很大，要找后台要接口！
            
            // A> 调度组入组
            group.enter()
            
            
            SDWebImageManager.shared().downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _, _) in
                // 将图片转换成二进制数据
                if let image = image,
                    let data = UIImagePNGRepresentation(image) {
                    // NSData 是 length 属性
                    length += data.count
                    
                    // 图像缓存成功,更新配图视图大小
                    vm.updateSingleImageSize(image: image)
                }
                
                print("缓存的image是\(String(describing: image))")
                
                // B>调度组出组, - 放在回调的最后一句
                group.leave()
            })
        }
        
        // C>监听调度组情况
        group.notify(queue: DispatchQueue.main) { 
            print("图像缓存完成 \(length / 1024) K")
            // 执行闭包回调
            finished(true, true)
        }
    }
}

